"""
FileKit creates file objects.
"""

import os
import shutil
import tempfile
import fimero.core.disk.PathKit as PathKit
import fimero.core.disk.NodeKit as NodeKit
import fimero.core.util.LogKit as LogKit
from NodeKit import TNode

MODE_TEXT = 'r'
MODE_TEXT_APPEND = 'a'
MODE_TEXT_WRITE = 'w'
MODE_BYTE = 'rb'
MODE_APPEND_BYTES = 'ab'
MODE_WRITE_BYTES = 'wb'

LOGGER = LogKit.get_logger(__name__)

################################################################################
# Classes
################################################################################

class TFile(TNode):
    """
    TFile is the base file type.
    """
    
    def __init__(self, path):
        """Initialize file instance with path."""
        TNode.__init__(self, path)
        
    def copy(self, path):
        """copy this file to path. Returns destination path."""
        path = PathKit.make(path)
        LOGGER.debug("Source: " + repr(self.path) + " to " + repr(path))
        shutil.copyfile(repr(self.path), repr(path))
        return path    
    
    def delete(self):
        """delete this file."""
        os.remove(repr(self.path))
        
    def get_handle(self, mode):
        """returns a handle to the underlying file with the specified mode."""
        return file(repr(self.path), mode)
    
    def read_bytes(self):
        """open this file, read all bytes, close file, return bytes."""
        handle = self.get_handle(MODE_BYTE)
        try:
            return handle.read()
        finally:
            handle.close()
            
    def write_bytes(self, bytes, mode=MODE_WRITE_BYTES):
        """open this file and write the specified bytes, clobbering existing 
        data."""
        
        handle = self.get_handle(mode)
        try:
            handle.write(bytes)
        finally:
            handle.close()
            
    def append_bytes(self, bytes):
        """open this file and append the specified bytes."""
        self.write_bytes(bytes, MODE_APPEND_BYTES)
        
    def touch(self):
        """If path doesn't exist, create an empty file. If it does exist, 
        update its utime."""
        if not self.exists():
            handle = os.open(repr(self), os.O_WRONLY | os.O_CREAT, 0666)
            os.close(handle)
            os.utime(repr(self), None)
        
# TODO : Move to TextFileKit
#class TTextFile(TFile):
#    """
#    TTextFile represents a text file.
#    """
#    def __init__(self, path):
#        """Initialize the text file instance with specified path."""
#        TFile.__init__(self, path)
#        
#    def read_text(self):
#        """Read all the file's text in one go."""
#        handle = self.get_handle(MODE_TEXT)
#        try:
#            return handle.read()
#        finally:
#            handle.close()
#            
#    def readlines(self):
#        """Return lines of text as a list."""
#        return self.get_handle(MODE_TEXT).readlines()
        
        
################################################################################
# Module methods
################################################################################

def make(path):
    """make a new File instance."""
    path = PathKit.make(path)
    return TFile(path)

def make_temp():
    """makes a temporary file."""
    filename = tempfile.mkstemp()[1]
    return make(filename)

def as_file(f, mode='r'):
    """
    fn -- something that could represent a file.
    mode -- file-mode to use to open the file.
    returns -- fn as a file.
    """
    try:
        # quack like a file?
        f.tell()
        return f
    except:
        newf = file(f, mode)
        return newf
    
